#!/usr/bin/env python
# encoding: utf-8
"""
@author:zwb
@file: articles.py
@contact: zwb15083976291@163.com
@time: 2021/12/11
"""
import math
import re

from django.db import transaction
from django.db.models import Q
from rest_framework import serializers

from common.models import BlogArticle, BlogCategorie, BlogTag, BlogTagArticle, BlogDraft
from utils.serializers.serializer import UpdateBaseSerializeMethodMixin, SpecifySerializeFieldModelSerializer, \
    PaginatorSerializer, SpecifySerializeFieldSerializer


class ArticleSerializer(UpdateBaseSerializeMethodMixin, SpecifySerializeFieldModelSerializer):
    id = serializers.IntegerField()
    articles_image_url = serializers.URLField()
    articles_type = serializers.ChoiceField(choices=[0, 1, 2])
    articles_status = serializers.ChoiceField(choices=[0, 1, 2])
    articles_reprint_url = serializers.URLField()
    articles_is_topping = serializers.ChoiceField(choices=[0, 1])
    tags = serializers.ListField(write_only=True)
    articles_content = serializers.CharField(write_only=True)
    word_count = serializers.IntegerField(read_only=True)
    reading_time = serializers.IntegerField(read_only=True)
    reading_quantity = serializers.IntegerField(read_only=True)
    comment_count = serializers.IntegerField(read_only=True)
    article_describe = serializers.CharField(write_only=True)  # 默认只写

    class Meta:
        model = BlogArticle
        fields = '__all__'

    def to_representation(self, instance):
        data = super().to_representation(instance)
        tags_id = BlogTagArticle.objects.filter(article_id=data.get('id')).values_list('tag_id', flat=True).order_by(
            "id")
        tags_data = BlogTag.objects.filter(id__in=tags_id).values("id", "tag_name")
        data['tags'] = tags_data
        categorie = BlogCategorie.objects.filter(id=data['categorie']).first()
        data["categorie"] = dict(id=categorie.id, categorie_name=categorie.categorie_name)
        # data['articles_is_topping'] = bool(data['articles_is_topping'])
        return data

    def validate_id(self, value):
        if not BlogArticle.objects.filter(id=value).exists():
            raise serializers.ValidationError("文章不存在")
        return value


class ArticleIdsListSerializer(SpecifySerializeFieldSerializer):
    ids = serializers.ListField(min_length=1)

    def validate_ids(self, value: list):
        if BlogArticle.objects.filter(id__in=value).count() != len(value):
            raise serializers.ValidationError("id不存在")
        return value


class CreateArticleSerializer(ArticleSerializer):
    draft_id = serializers.IntegerField(write_only=True)

    def validate_articles_title(self, value):
        if BlogArticle.objects.filter(articles_title=value).first():
            raise serializers.ValidationError("文章标题已存在")
        return value

    def validate_categorie(self, value):
        if not BlogCategorie.objects.filter(id=value).first():
            raise serializers.ValidationError("分类不存在")
        return value

    def validate_tags(self, value: list):
        if BlogTag.objects.filter(id__in=value).count() != len(value):
            raise serializers.ValidationError("标签不存在")
        return value

    def validate(self, attrs):
        if int(attrs.get("articles_type")) != 0 and (not attrs.get("articles_reprint_url")):
            raise serializers.ValidationError("必须存在转载/翻译链接地址")

        # 如果为原创，将链接地址置为空
        if int(attrs.get("articles_type")) == 0:
            attrs["articles_reprint_url"] = ""
        return attrs

    def validate_draft_id(self, value):
        if not BlogDraft.objects.filter(id=value).exists():
            raise serializers.ValidationError("数据不存在")
        return value

    def create(self, validated_data):
        tags = validated_data.get("tags")
        draft_id = validated_data.get("draft_id", None)
        categorie = validated_data.get("categorie")
        create_data = self._get_model_data(validated_data)
        # 计算 word_count,reading_time
        create_data['word_count'] = len(re.sub(u"([^\u4e00-\u9fa5\u0030-\u0039\u0041-\u005a\u0061-\u007a])", "",
                                               create_data.get("articles_content")))
        create_data['reading_time'] = math.ceil(create_data['word_count'] / 400)
        create_data['article_describe'] = \
            re.sub(u"[#>*\n\t\r]", "", create_data.get("articles_content")).replace(" ", '')[:200]
        # 创建数据
        with transaction.atomic():
            article = BlogArticle.objects.create(**create_data)
            for tag in tags:
                BlogTagArticle.objects.create(tag_id=tag, article_id=article.id)
                tag_obj = BlogTag.objects.filter(id=tag).first()
                tag_obj.articles_count += 1
                tag_obj.save()
            categorie_obj = BlogCategorie.objects.filter(id=categorie).first()
            categorie_obj.categorie_count += 1
            categorie_obj.save()
            if draft_id:
                BlogDraft.objects.filter(id=draft_id).delete()
        return article


class UpdateArticleSerializer(CreateArticleSerializer):

    def validate_articles_title(self, value):
        return value

    def validate(self, attrs):
        result = super().validate(attrs)
        articles_title = result.get("articles_title", None)
        articles_id = result.get("id", None)
        if (articles_title is not None) and (articles_id is not None):
            if BlogArticle.objects.filter(Q(articles_title=articles_title) & ~Q(id=articles_id)).exists():
                raise serializers.ValidationError("文章标题重复")
        return attrs


class ArticlesPaginatorSerializer(PaginatorSerializer):
    categorie = serializers.IntegerField()
    articles_type = serializers.ChoiceField(choices=[0, 1, 2])
    articles_status = serializers.ChoiceField(choices=[0, 1, 2])

    def validate_categorie(self, value):
        if not BlogCategorie.objects.filter(id=value).exists():
            raise serializers.ValidationError("分类不存在")
        return value


class DraftSerializer(UpdateBaseSerializeMethodMixin, SpecifySerializeFieldModelSerializer):
    id = serializers.IntegerField()
    draft_data = serializers.CharField(min_length=10)

    class Meta:
        fields = '__all__'
        model = BlogDraft


class DraftSerializerValidate():
    def validate_draft_title(self, value):
        if BlogArticle.objects.filter(articles_title=value).exists() or BlogDraft.objects.filter(
                draft_title=value).exists():
            raise serializers.ValidationError("文章标题重复")
        return value

    def validate_id(self, value):
        if not BlogDraft.objects.filter(id=value).exists():
            raise serializers.ValidationError("数据不存在")
        return value


class CreateDraftSerializer(DraftSerializer, DraftSerializerValidate):
    pass


class UpdateDraftSerializer(DraftSerializer, DraftSerializerValidate):
    def validate_draft_title(self, value):
        return value

    def validate(self, attrs):
        draft_title = attrs.get("draft_title")
        draft_id = attrs.get("id")
        if BlogArticle.objects.filter(articles_title=draft_title).exists() or BlogDraft.objects.filter(
                draft_title=draft_title).exclude(id=draft_id).exists():
            raise serializers.ValidationError("文章标题重复")
        return attrs


class DeleteDraftSerializer(DraftSerializer, DraftSerializerValidate):
    pass


class GetDraftSerializer(DraftSerializer, DraftSerializerValidate):
    id = serializers.IntegerField()
    pass
